/*
 * tcp_ip_client.c
 *
 *  Created on: Aug 20, 2012
 *      Author: drew
 */

#include "tcp_ip_client.h"

#define GETBUFFSIZE( x )  sizeof( x )/sizeof( char )

void * vpTcpIpClientListenerRunLoop( void * pvParameters )
{
  xpTcpIpClientDescription xpTcpIpClientObj = (xpTcpIpClientDescription)pvParameters;

  char cReadBuffer[1024];

  for( ;; )
  {
    if( read( xpTcpIpClientObj->iSocket, cReadBuffer, 1 ) <= 0 )
    {
      perror("Client Read");
      break;
    }

    xpTcpIpClientObj->vpCallback( cReadBuffer, 1 );
  }

  return NULL;
}

xpTcpIpClientDescription xpTcpIpClientCreateObject( char * cpAddress, int iPort, vpTcpIpClientRxCallback vpCallback )
{
  xpTcpIpClientDescription xpTcpIpObj = (xpTcpIpClientDescription)malloc( sizeof( xTcpIpClientDescription ) );

  xpTcpIpObj->iPort = iPort;

  strcpy( xpTcpIpObj->cpHostAddress, cpAddress );

  xpTcpIpObj->vpCallback = vpCallback;

  return xpTcpIpObj;
}

void vTcpIpClientDestroyObject( xpTcpIpClientDescription xpTcpIpClientObject )
{
  free( xpTcpIpClientObject );
}

int iTcpIpClientInitialize( xpTcpIpClientDescription xpTcpIpClientObject )
{
  xpTcpIpClientObject->xpHost = gethostbyname( xpTcpIpClientObject->cpHostAddress );

  if( (xpTcpIpClientObject->iSocket = socket(AF_INET, SOCK_STREAM, 0) ) == -1)
  {
    perror( "Socket" );
    return 1;
  }

  xpTcpIpClientObject->xServerAddress.sin_family = AF_INET;
  xpTcpIpClientObject->xServerAddress.sin_port = htons( xpTcpIpClientObject->iPort );

  /* TODO: update this. it seems silly to assign and then re-assign */
  xpTcpIpClientObject->xServerAddress.sin_addr = *((struct in_addr *)xpTcpIpClientObject->xpHost->h_addr_list[0]);

  memset( &xpTcpIpClientObject->xServerAddress.sin_zero, '\0', 8);

  if( connect( xpTcpIpClientObject->iSocket, (struct sockaddr *)&xpTcpIpClientObject->xServerAddress, sizeof( struct sockaddr ) ) == -1)
  {
    perror( "Connect" );
    return 1;
  }

  if( pthread_create( &xpTcpIpClientObject->xThreadHandle, NULL, vpTcpIpClientListenerRunLoop, (void*)xpTcpIpClientObject ) )
  {
    perror( "Thread Spawn" );
    return 1;
  }

  return 0;
}

void vTcpIpClientCleanup( xpTcpIpClientDescription xpTcpIpClientObject )
{
  close( xpTcpIpClientObject->iSocket );
}

int iTcpIpClientPrint( xpTcpIpClientDescription xpTcpIpClientObject, char * cpBuff, int iLength )
{
  int iReadReturn;
  iReadReturn = write( xpTcpIpClientObject->iSocket, cpBuff, iLength );

  if( iReadReturn < 0 )
  {
    perror( "Read" );
  }

  if( iReadReturn == 0 )
  {
    printf("ERROR: Socket is closed\n");
  }

  return (iReadReturn <= 0);
}


